/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 *%
 *%       mmse_init.c
 *%       Author: Sharon Lee
 *%       History:
 *%                        Created by Sharon Lee in August, 2019
 *%
 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

/* Include files */
#include <string.h>
#include "define.h"
#include "struct.h"
#include "packfft.h"
#include "memalloc.h"
#include "mmse_init.h"

/* Function Definitions */
EXPORT void NR_para(ssp_para_struct *para, float *aa, float *mu)
{
  ssp_para_struct *para_obj;
  unsigned short temp;

  /* NR Parameters */
  para_obj = para;
  para_obj->para_nr_noise_coeff = 2;

  //para_obj->para_nr_init_sile_time = MIN(MAX(para_obj->para_nr_init_sile_time, 0), 250);
  //if (fs == 16000.0F) {
    //*nenr_silence_time = para_obj->para_nr_init_sile_time*2;
  //} else {
    //*nenr_silence_time = para_obj->para_nr_init_sile_time;
  //}

  temp = MIN(MAX(para_obj->para_nr_snr_coeff, 0), 25);
  //if (temp >= 0 && temp <= 3) {    /* for low SNR, [0, 3] = > [0.6, 0.9] */
  if (temp <= 3) {    /* for low SNR, [0, 3] = > [0.6, 0.9] */
      *aa = (float)(0.60 + temp * 0.1);    /* the speed of priori SNR tracking */
  }
  else if (temp > 3 && temp <= 10) {    /* for middle SNR, [4, 10] => [0.91, 0.97] */
      *aa = (float)(0.90 + (temp - 3) * 0.01);    /* the speed of priori SNR tracking */
  }
  else if (temp > 10 && temp <= 20) {    /* for high SNR, [11, 20] => [0.972, 0.99] */
      *aa = (float)(0.97 + (temp - 10) * 0.002);    /* the speed of priori SNR tracking */
  }
  else {    /* for higher SNR, [21, 25] => [0.991, 0.995] */
      *aa = (float)(0.99 + (temp - 20) * 0.001);    /* the speed of priori SNR tracking */
  }

  temp = MIN(MAX(para_obj->para_nr_noise_coeff, 0), 14);
  *mu = (float)(0.99 - temp * 0.01);

}

EXPORT NRState *NR_init(int frame_size, float fs, float aa, float mu)
{
    int i;

    static const float fv0[320] = { 0.00978696439F, 0.0195724051F, 0.0293563232F,
    0.0391375758F, 0.0489150211F, 0.0586875156F, 0.0684547871F, 0.0782151669F,
    0.0879682377F, 0.0977126881F, 0.107447952F, 0.117172875F, 0.126886666F,
    0.136588231F, 0.146276712F, 0.155951113F, 0.165610686F, 0.175254285F,
    0.184881195F, 0.194490388F, 0.204080895F, 0.213651851F, 0.223202422F,
    0.232731596F, 0.242238432F, 0.251722068F, 0.261181623F, 0.270616144F,
    0.280024707F, 0.289406538F, 0.298760593F, 0.308086067F, 0.317382F,
    0.32664752F, 0.33588177F, 0.345083892F, 0.354252934F, 0.363388F, 0.37248826F,
    0.381552905F, 0.390580982F, 0.399571627F, 0.408524F, 0.417437255F,
    0.426310569F, 0.435143F, 0.443933755F, 0.452682018F, 0.461386859F,
    0.470047563F, 0.478663206F, 0.487233073F, 0.495756179F, 0.50423187F,
    0.512659192F, 0.521037519F, 0.529365838F, 0.537643492F, 0.545869648F,
    0.554043531F, 0.562164307F, 0.570231259F, 0.578243613F, 0.586200595F,
    0.594101369F, 0.601945281F, 0.609731555F, 0.617459357F, 0.62512809F,
    0.632736921F, 0.640285134F, 0.647772F, 0.655196846F, 0.662559F, 0.669857562F,
    0.677092075F, 0.68426168F, 0.691365719F, 0.698403656F, 0.705374539F,
    0.712277949F, 0.719113111F, 0.725879431F, 0.732576191F, 0.739202797F,
    0.745758593F, 0.752243042F, 0.75865525F, 0.764995F, 0.771261334F,
    0.77745384F, 0.783571839F, 0.789614856F, 0.795582235F, 0.80147332F,
    0.807287753F, 0.813024819F, 0.818684F, 0.824264765F, 0.829766572F,
    0.835188925F, 0.84053123F, 0.845793068F, 0.850973964F, 0.85607326F,
    0.861090541F, 0.866025388F, 0.870877266F, 0.875645757F, 0.880330384F,
    0.88493067F, 0.889446199F, 0.893876493F, 0.898221254F, 0.902479887F,
    0.906652153F, 0.910737574F, 0.914735734F, 0.918646276F, 0.922468841F,
    0.926203072F, 0.929848552F, 0.933404922F, 0.936872F, 0.940249264F,
    0.94353646F, 0.946733356F, 0.949839532F, 0.952854693F, 0.955778599F,
    0.958611F, 0.961351573F, 0.964000046F, 0.966556191F, 0.969019771F,
    0.971390486F, 0.973668218F, 0.975852728F, 0.977943659F, 0.979940951F,
    0.981844425F, 0.983653843F, 0.985368967F, 0.986989796F, 0.988516092F,
    0.989947617F, 0.99128443F, 0.992526233F, 0.993673F, 0.994724631F,
    0.995680928F, 0.996541858F, 0.997307301F, 0.997977257F, 0.998551607F,
    0.999030352F, 0.999413371F, 0.999700665F, 0.999892235F, 0.999988F, 0.999988F,
    0.999892235F, 0.999700665F, 0.999413371F, 0.999030352F, 0.998551607F,
    0.997977257F, 0.997307301F, 0.996541858F, 0.995680928F, 0.994724631F,
    0.993673F, 0.992526233F, 0.99128443F, 0.989947617F, 0.988516092F,
    0.986989796F, 0.985368967F, 0.983653843F, 0.981844425F, 0.979940951F,
    0.977943659F, 0.975852728F, 0.973668218F, 0.971390486F, 0.969019771F,
    0.966556191F, 0.964000046F, 0.961351573F, 0.958611F, 0.955778599F,
    0.952854693F, 0.949839532F, 0.946733356F, 0.94353646F, 0.940249264F,
    0.936872F, 0.933404922F, 0.929848552F, 0.926203072F, 0.922468841F,
    0.918646276F, 0.914735734F, 0.910737574F, 0.906652153F, 0.902479887F,
    0.898221254F, 0.893876493F, 0.889446199F, 0.88493067F, 0.880330384F,
    0.875645757F, 0.870877266F, 0.866025388F, 0.861090541F, 0.85607326F,
    0.850973964F, 0.845793068F, 0.84053123F, 0.835188925F, 0.829766572F,
    0.824264765F, 0.818684F, 0.813024819F, 0.807287753F, 0.80147332F,
    0.795582235F, 0.789614856F, 0.783571839F, 0.77745384F, 0.771261334F,
    0.764995F, 0.75865525F, 0.752243042F, 0.745758593F, 0.739202797F,
    0.732576191F, 0.725879431F, 0.719113111F, 0.712277949F, 0.705374539F,
    0.698403656F, 0.691365719F, 0.68426168F, 0.677092075F, 0.669857562F,
    0.662559F, 0.655196846F, 0.647772F, 0.640285134F, 0.632736921F, 0.62512809F,
    0.617459357F, 0.609731555F, 0.601945281F, 0.594101369F, 0.586200595F,
    0.578243613F, 0.570231259F, 0.562164307F, 0.554043531F, 0.545869648F,
    0.537643492F, 0.529365838F, 0.521037519F, 0.512659192F, 0.50423187F,
    0.495756179F, 0.487233073F, 0.478663206F, 0.470047563F, 0.461386859F,
    0.452682018F, 0.443933755F, 0.435143F, 0.426310569F, 0.417437255F, 0.408524F,
    0.399571627F, 0.390580982F, 0.381552905F, 0.37248826F, 0.363388F,
    0.354252934F, 0.345083892F, 0.33588177F, 0.32664752F, 0.317382F,
    0.308086067F, 0.298760593F, 0.289406538F, 0.280024707F, 0.270616144F,
    0.261181623F, 0.251722068F, 0.242238432F, 0.232731596F, 0.223202422F,
    0.213651851F, 0.204080895F, 0.194490388F, 0.184881195F, 0.175254285F,
    0.165610686F, 0.155951113F, 0.146276712F, 0.136588231F, 0.126886666F,
    0.117172875F, 0.107447952F, 0.0977126881F, 0.0879682377F, 0.0782151669F,
    0.0684547871F, 0.0586875156F, 0.0489150211F, 0.0391375758F, 0.0293563232F,
    0.0195724051F, 0.00978696439F };

    static const float fv1[320] = { 0.0107656615F, 0.0215296466F, 0.0322919562F,
    0.043051336F, 0.0538065247F, 0.0645562708F, 0.0753002688F, 0.0860366821F,
    0.0967650637F, 0.107483961F, 0.118192747F, 0.128890172F, 0.139575332F,
    0.150247052F, 0.160904393F, 0.171546221F, 0.182171762F, 0.19277972F,
    0.203369319F, 0.213939428F, 0.224488989F, 0.235017046F, 0.245522663F,
    0.256004751F, 0.266462266F, 0.276894271F, 0.287299782F, 0.297677755F,
    0.308027178F, 0.318347186F, 0.328636646F, 0.338894695F, 0.349120229F,
    0.359312266F, 0.369469941F, 0.379592299F, 0.38967824F, 0.399726808F,
    0.40973708F, 0.419708192F, 0.429639101F, 0.439528793F, 0.449376404F,
    0.459180981F, 0.468941629F, 0.478657305F, 0.488327146F, 0.497950226F,
    0.507525563F, 0.517052352F, 0.526529551F, 0.535956383F, 0.545331836F,
    0.554655075F, 0.563925147F, 0.573141277F, 0.582302451F, 0.591407835F,
    0.600456655F, 0.609447896F, 0.618380725F, 0.627254426F, 0.636068F,
    0.64482069F, 0.653511524F, 0.662139833F, 0.670704722F, 0.679205298F,
    0.687640905F, 0.696010649F, 0.704313636F, 0.71254921F, 0.720716536F,
    0.7288149F, 0.736843348F, 0.744801283F, 0.752687871F, 0.760502279F,
    0.768244F, 0.775912F, 0.783505738F, 0.791024446F, 0.798467398F, 0.805833817F,
    0.813123107F, 0.820334494F, 0.827467382F, 0.834520817F, 0.841494501F,
    0.84838748F, 0.855199218F, 0.861929059F, 0.868576348F, 0.875140488F,
    0.881620646F, 0.888016522F, 0.894327343F, 0.900552392F, 0.906691253F,
    0.91274327F, 0.918707848F, 0.924584389F, 0.930372417F, 0.936071396F,
    0.94168061F, 0.947199643F, 0.952627957F, 0.957965F, 0.963210344F,
    0.968363464F, 0.973423779F, 0.978390813F, 0.983264148F, 0.988043427F,
    0.992727876F, 0.997317374F, 1.00181139F, 1.00620937F, 1.01051092F,
    1.01471579F, 1.01882339F, 1.02283347F, 1.02674544F, 1.03055918F, 1.03427422F,
    1.03789008F, 1.04140675F, 1.04482353F, 1.04814017F, 1.05135643F, 1.05447209F,
    1.05748677F, 1.06040013F, 1.0632118F, 1.06592178F, 1.06852961F, 1.07103503F,
    1.07343805F, 1.07573807F, 1.0779351F, 1.08002889F, 1.08201921F, 1.08390594F,
    1.08568883F, 1.08736777F, 1.08894241F, 1.09041286F, 1.09177887F, 1.09304035F,
    1.09419715F, 1.09524906F, 1.09619606F, 1.09703803F, 1.09777498F, 1.09840679F,
    1.09893346F, 1.09935474F, 1.09967077F, 1.09988153F, 1.09998679F, 1.09998679F,
    1.09988153F, 1.09967077F, 1.09935474F, 1.09893346F, 1.09840679F, 1.09777498F,
    1.09703803F, 1.09619606F, 1.09524906F, 1.09419715F, 1.09304035F, 1.09177887F,
    1.09041286F, 1.08894241F, 1.08736777F, 1.08568883F, 1.08390594F, 1.08201921F,
    1.08002889F, 1.0779351F, 1.07573807F, 1.07343805F, 1.07103503F, 1.06852961F,
    1.06592178F, 1.0632118F, 1.06040013F, 1.05748677F, 1.05447209F, 1.05135643F,
    1.04814017F, 1.04482353F, 1.04140675F, 1.03789008F, 1.03427422F, 1.03055918F,
    1.02674544F, 1.02283347F, 1.01882339F, 1.01471579F, 1.01051092F, 1.00620937F,
    1.00181139F, 0.997317374F, 0.992727876F, 0.988043427F, 0.983264148F,
    0.978390813F, 0.973423779F, 0.968363464F, 0.963210344F, 0.957965F,
    0.952627957F, 0.947199643F, 0.94168061F, 0.936071396F, 0.930372417F,
    0.924584389F, 0.918707848F, 0.91274327F, 0.906691253F, 0.900552392F,
    0.894327343F, 0.888016522F, 0.881620646F, 0.875140488F, 0.868576348F,
    0.861929059F, 0.855199218F, 0.84838748F, 0.841494501F, 0.834520817F,
    0.827467382F, 0.820334494F, 0.813123107F, 0.805833817F, 0.798467398F,
    0.791024446F, 0.783505738F, 0.775912F, 0.768244F, 0.760502279F, 0.752687871F,
    0.744801283F, 0.736843348F, 0.7288149F, 0.720716536F, 0.71254921F,
    0.704313636F, 0.696010649F, 0.687640905F, 0.679205298F, 0.670704722F,
    0.662139833F, 0.653511524F, 0.64482069F, 0.636068F, 0.627254426F,
    0.618380725F, 0.609447896F, 0.600456655F, 0.591407835F, 0.582302451F,
    0.573141277F, 0.563925147F, 0.554655075F, 0.545331836F, 0.535956383F,
    0.526529551F, 0.517052352F, 0.507525563F, 0.497950226F, 0.488327146F,
    0.478657305F, 0.468941629F, 0.459180981F, 0.449376404F, 0.439528793F,
    0.429639101F, 0.419708192F, 0.40973708F, 0.399726808F, 0.38967824F,
    0.379592299F, 0.369469941F, 0.359312266F, 0.349120229F, 0.338894695F,
    0.328636646F, 0.318347186F, 0.308027178F, 0.297677755F, 0.287299782F,
    0.276894271F, 0.266462266F, 0.256004751F, 0.245522663F, 0.235017046F,
    0.224488989F, 0.213939428F, 0.203369319F, 0.19277972F, 0.182171762F,
    0.171546221F, 0.160904393F, 0.150247052F, 0.139575332F, 0.128890172F,
    0.118192747F, 0.107483961F, 0.0967650637F, 0.0860366821F, 0.0753002688F,
    0.0645562708F, 0.0538065247F, 0.043051336F, 0.0322919562F, 0.0215296466F,
    0.0107656615F };

  NRState *st = (NRState *)mem_alloc(sizeof(NRState));
  st->Fs = fs;
  st->frame_size = frame_size;
  st->aa = aa;
  st->mu = mu;

  st->nr_fft_table = speech_fft_init(2*2*st->frame_size);
  st->ana_win = (float*)mem_alloc(2*st->frame_size*sizeof(float));
  st->syn_win = (float*)mem_alloc(2*st->frame_size*sizeof(float));
  st->x_old = (short*)mem_alloc(st->frame_size*sizeof(short));
  st->y_old = (float*)mem_alloc(st->frame_size*sizeof(float));
  st->Xk_prev = (float*)mem_alloc((2*st->frame_size+1)*sizeof(float));
  st->noise_mean = (float*)mem_alloc((2*st->frame_size+1)*sizeof(float));
  st->noise_mu2 = (float*)mem_alloc((2*st->frame_size+1)*sizeof(float));
  st->amp_inst_band = (float*)mem_alloc(5*3*sizeof(float));
  st->noisy_st_trough = (float*)mem_alloc(5*sizeof(float));
  st->noisy_st_peak = (float*)mem_alloc(5*sizeof(float));
  st->amp_inst_sum_hist = (float*)mem_alloc(3*sizeof(float));
  st->float_x = (float*)mem_alloc(2*st->frame_size*sizeof(float));

  for (i = 0; i < 2*st->frame_size; i++) {
    st->ana_win[i] = fv0[i];
    st->syn_win[i] = fv1[i];
  }

  for (i = 0; i < st->frame_size; i++) {
    st->x_old[i] = 0;
    st->y_old[i] = 0.0F;
  }

  for (i = 0; i < 2*st->frame_size+1; i++) {
    //Xk_prev[i].re = 0.0F;
    //Xk_prev[i].im = 0.0F;
    st->Xk_prev[i] = 0.0F;
    st->noise_mean[i] = 0.0F;
    st->noise_mu2[i] = 0.0F;
  }

  for (i = 0; i < 15; i++) {
    st->amp_inst_band[i] = 0.0F;
  }

  for (i = 0; i < 5; i++) {
    st->noisy_st_trough[i] = 0.0F;
    st->noisy_st_peak[i] = 0.0F;
  }

  for (i = 0; i < 3; i++) {
    st->amp_inst_sum_hist[i] = 0.0F;
  }

  st->eta = 0.15F;
  st->ksi_min = 0.0031622777F;
  st->vad_slope_cnt = 0.0F;
  st->vad_slope = 0.0F;
  st->vad_dr_cnt = 0.0F;
  st->vad_dr = 0.0F;
  st->vad_mmse = 0.0F;
  st->vad_mmse_cnt = 0.0F;
  if (fs == 16000)
    st->vad_mmse_cnt_para = 4;    /* last at least 40ms, once the mmse vad goes up, keep the circumstance a period of time to get better speech quality */
  else if (fs == 8000)
    st->vad_mmse_cnt_para = 2;    /* last at least 40ms, once the mmse vad goes up, keep the circumstance a period of time to get better speech quality */

  return st;

}

EXPORT void NR_free(NRState *st)
{
  speech_fft_free(st->nr_fft_table);
  mem_free(st->ana_win);
  mem_free(st->syn_win);
  mem_free(st->x_old);
  mem_free(st->y_old);
  mem_free(st->Xk_prev);
  mem_free(st->noise_mean);
  mem_free(st->noise_mu2);
  mem_free(st->amp_inst_band);
  mem_free(st->noisy_st_trough);
  mem_free(st->noisy_st_peak);
  mem_free(st->amp_inst_sum_hist);
  mem_free(st->float_x);

  mem_free(st);

}


